﻿using System.IO.Ports;

namespace CSharpAllDemo.Serial
{
    public class SerialPortManager
    {
        public delegate void WaitReceivedCallback(bool isSuccess, byte[] messageByte);
        public delegate void ReceivedCallback(byte[] messageByte);

        // 私有静态实例
        private static readonly SerialPortManager _instance = new SerialPortManager();
        // 公共静态方法，返回实例
        public static SerialPortManager Instance => _instance;

        private SerialPort mSerialPort;

        private ReceivedCallback? mReceivedCallback = null;

        private WaitReceivedCallback? mWaitReceivedCallback = null;


        // 私有构造函数，防止外部实例化
        private SerialPortManager()
        {
            this.mSerialPort = new SerialPort()
            {
                DataBits = 8,
                StopBits = StopBits.One,
                Parity = Parity.None,
                BaudRate = 115200,
                //PortName = "COM3",
                ReadBufferSize = 40960,
                WriteBufferSize = 40960,
            };
            this.mSerialPort.DataReceived += OnPortReceived;
        }
        private void OnPortReceived(object sender, SerialDataReceivedEventArgs e)
        {
            var arr = new byte[this.mSerialPort.BytesToRead];
            this.mSerialPort.Read(arr, 0, arr.Length);

            //收到数据
            if (this.mWaitReceivedCallback != null)
            {
                this.mWaitReceivedCallback(true, arr);
                this.mWaitReceivedCallback = null;
            }
            if (this.mReceivedCallback != null)
            {
                this.mReceivedCallback(arr);
            }

        }

        public string[] GetPortNames()
        {
            return SerialPort.GetPortNames();
        }

        public bool Open(string portName, int baudRate, ReceivedCallback receivedCallback)
        {
            try
            {
                if (this.mSerialPort.IsOpen) this.mSerialPort.Close();
                this.mReceivedCallback = receivedCallback;
                this.mSerialPort.PortName = portName;
                this.mSerialPort.BaudRate = baudRate;
                this.mSerialPort.Open();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        public bool Close()
        {
            try
            {
                if (this.mSerialPort.IsOpen) this.mSerialPort.Close();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public void Write(byte[] commandByte)
        {
            if (!this.mSerialPort.IsOpen) return;
            this.mSerialPort.Write(commandByte, 0, commandByte.Length);//发送数据
        }

        public void WriteCallBack(byte[] commandByte, WaitReceivedCallback waitReceivedCallback, int milliseconds)
        {
            if (!this.mSerialPort.IsOpen) return;
            this.mSerialPort.Write(commandByte, 0, commandByte.Length);//发送数据
            this.mWaitReceivedCallback = waitReceivedCallback;
            Task.Factory.StartNew(async () =>
            {
                await Task.Delay(milliseconds);
                if (this.mWaitReceivedCallback != null)
                {
                    this.mWaitReceivedCallback(false, null);
                    this.mWaitReceivedCallback = null;
                }

            });

        }



    }
}
